using System.Linq;
using Jink.Core.Handlers.Annotations;
using Jink.Core.Handlers.Bind.Exceptions;
using XenoGears.Functional;
using XenoGears.Assertions;

namespace Jink.Core.Handlers.Bind
{
    internal static class Api
    {
        public static BoundHandler BindHandler(this CoreRequest request)
        {
            var matches = HandlersRegistry.All.Select(h => h.Match(request)).ToReadOnly();
            if (matches.Count(m => m.Success) != 1)
            {
                if (matches.IsNotEmpty(m => m.Success)) throw new BindAmbiguousException(matches);
                if (matches.Any(m => m.Status == BindStatus.ArgumentsMismatch)) throw new ArgumentsMismatchException(matches);
                if (matches.Any(m => m.Status == BindStatus.VerbMismatch)) throw new VerbMismatchException(matches);
                if (matches.Any(m => m.Status == BindStatus.UrlMismatch)) throw new UrlMismatchException(matches);
                throw AssertionHelper.Fail();
            }

            var match = matches.Single(m => m.Success);
            return match.BoundHandler;
        }
    }
}